﻿#include "Compressor.h"
#include "lang/StringFormat.hpp"
#include "util/Util.h"
using namespace yzrilyzr_lang;
using namespace yzrilyzr_util;
using namespace yzrilyzr_interpolator;
namespace yzrilyzr_dsp{
	Compressor::Compressor(){
		registerParamGain("PreGain", &preGain);
		registerParamGain("PostGain", &postGain);
		registerParamInterpolator("IOFunction", &ioFunction);
		registerSub("Env", &envDetect);
	}
	Compressor::Compressor(u_sample preGain, u_sample postGain,
						   u_time_ms attack, u_time_ms hold, u_time_ms release,
						   int limitType,
						   std::shared_ptr<Interpolator> ioFunction) :
		preGain(preGain),
		postGain(postGain),
		ioFunction(ioFunction){
		envDetect.attack=attack;
		envDetect.hold=hold;
		envDetect.release=release;
		envDetect.type=limitType;
	}

	u_sample Compressor::procDsp(u_sample src){
		u_sample envInput=src * preGain;
		envDetect.procDsp(envInput);
		u_sample envVal=envDetect.getEnvValue();
		u_sample targetGain=1;
		if(envVal > 0){
			u_sample fu=ioFunction->y(envVal);
			targetGain=fu / envVal;
		}
		targetGain=Util::clamp(targetGain, static_cast<u_sample>(0.0), static_cast<u_sample>(999.0));
		finalGain=targetGain * preGain * postGain;
		return src * finalGain;
	}
	void Compressor::init(u_sample_rate sampleRate){
		this->sampleRate=sampleRate;
		envDetect.init(sampleRate);
	}
	void Compressor::resetMemory(){
		envDetect.resetMemory();
	}
	std::shared_ptr<DSP> Compressor::cloneDSP(){
		return std::make_shared < Compressor>(preGain, postGain,
											  envDetect.attack, envDetect.hold, envDetect.release,
											  envDetect.type,
											  ioFunction);
	}
	void Compressor::cloneParam(DSP * obj1){
		if(auto other=dynamic_cast<Compressor *>(obj1)){
			preGain=other->preGain;
			postGain=other->postGain;
			envDetect.cloneParam(static_cast<DSP *>(&other->envDetect));
			ioFunction=other->ioFunction;
		}
	}
	String Compressor::toString()const{
		return StringFormat::object2string("Compressor", preGain, postGain,
										   envDetect.attack, envDetect.hold, envDetect.release,
										   envDetect.type,
										   ioFunction);
	}
}